/* 

A bar chart made out of pictures, using the Google Visalization API.
Each picture has a head, and a tail that has a length proportional to the bar size.
The idea was Taken from BarsOfStuff program from Google Code 

Data Format
  First column string (label)
  Second column number (value)
  or
  Onw row of numbers

Configuration options:
  min: The minimal value (default=0)
  max: The maximal value (default=actual maximal value)
  title: Text for a title above the chart (default=none)
  canSelect: Boolean, if true, users can click on bars
  width: width in pixels or as percent from parent container (default = '100%')
  type: Name (case insensitive) of image type. Supported types are:
 	Drop

Methods
  setSelection
  getSelection

Events
  select

*/

MyWater = function(container) {
  this.container = container;
  
  this.bars = []; 
  this.uid = MyWater.nextId++;
  this.selection = [];
};

// Global constant to prevent namespace collision between 2 chart
MyWater.nextId = 0;

MyWater.protocol = 'https:' == document.location.protocol ? 'https:' : 'http:';

MyWater.STYLES = [
  {name:'drop', img: 'drop.png', height: 40}
];

MyWater.IMGPATH = MyWater.protocol + '//mywater.googlecode.com/svn/waterbar/';

MyWater.prototype.escapeHtml = function(text) {
  if (text == null) {
    return '';
  }
  return text.replace(/&/g, '&amp;').
      replace(/</g, '&lt;').
      replace(/>/g, '&gt;').
      replace(/"/g, '&quot;');
};

MyWater.prototype.draw = function(data, options) {
  var container = this.container;
  var rows = data.getNumberOfRows();
  if (rows < 1) {
    container.innerHTML = 'Error: No data (no rows)';
    return;
  }
        
  var bars = [];
  this.bars = bars;        
  var cols = data.getNumberOfColumns();
  if (cols >= 2 && data.getColumnType(0) == 'string' && data.getColumnType(1) == 'number') {
    // Labels column and values column
    for (var rowInd = 0; rowInd < rows; rowInd++) {
      var v = data.getValue(rowInd, 1);
      if (v >= 0) {
        bars.push({value: v, formatted: data.getFormattedValue(rowInd, 1), 
            label: data.getValue(rowInd, 0), dataRow: rowInd});
      }
    }
  } else {
    // Column labels and a single values row
    for (var colInd = 0; colInd < cols; colInd++) {
      if (data.getColumnType(colInd) == 'number') {
        var v = data.getValue(0, colInd);
        if (v >= 0) {
          bars.push({value: v, formatted: data.getFormattedValue(0, colInd),
             label: data.getColumnLabel(colInd), dataCol: colInd});
        }
      }
    }
  }
        
  if (bars.length < 1) {
    container.innerHTML = '<span class="barsofmoney-error">MyWater Error: Expecting some numeric values</span>';
    return;
  }
        
  var minValue = 0;
  var maxValue = bars[0].value;
  for (var i = 1; i < bars.length; i++) {
    maxValue = Math.max(maxValue, bars[i].value);
  }

  var prefMinValue = options['min'];
  var prefMaxValue = options['max'];
  if (prefMinValue != null || prefMaxValue != null) {
    var min = prefMinValue || 0;
    var max = prefMaxValue || maxValue;
    if (min >= 0 && max > 0 && min < max) {
      minValue = min;
      maxValue = max;
    }
  }

  var range = maxValue - minValue;
  
  var styleInd = 0;
  var type = options['type'];
  if (type) {
    type = type.toLowerCase();
    for (var i = 0; i < MyWater.STYLES.length; i++) {
      if (MyWater.STYLES[i].name == type) {
        styleInd = i;
        break;
      }
    }  
  }
        
  var chartStyle = MyWater.STYLES[styleInd];

  // Set up the skeleton table
  var html = [];

  var width = options['width'] || '100%';
  html.push('<table width="', width, '">');  

  var header = options['title'];
  if (header) {
    html.push('<tr><td colspan="', bars.length, '" class="MyWater-title">', 
        this.escapeHtml(header), '</td></tr>');
  }

  for (var i = 0; i < bars.length; i++) {
    var bar = bars[i];
    var barDomId = 'pilesofmoney-b-' + this.uid + '-' + i; 
    bars[i].domId = barDomId;
    html.push('<tr><td class="MyWater-label" height="', chartStyle.height, '">',
        '<b>', this.escapeHtml(bar.label), '</b>', 
        '<br />', this.escapeHtml(bar.formatted), 
        '</td>');
    html.push('<td id="', barDomId, '" width="95%" nowrap="true"></td></tr>');
  }
  html.push('</table>');
  container.innerHTML = html.join('');

  // Measure the effective width for charts
  var headWidth = chartStyle.headWidth || 0;
  var maxImgWidth = document.getElementById(bars[0].domId).offsetWidth - 24; // To allow adding a scrollbar
  maxImgWidth = Math.max(maxImgWidth, headWidth + 100);
  var maxBarWidth = maxImgWidth - headWidth;

  // Draw the bars
  for (var i = 0; i < bars.length; i++) {
    var bar = bars[i];
    var v = Math.max(0, bar.value);
    var pct = range == 0 ? 0 : Math.min(1, (v - minValue) / range);
    var barWidth = Math.round(pct * maxBarWidth);
    html = [];
    if (headWidth > 0) {
      html.push('<table cellpadding="0" cellspacing="0"><tr><td>');
    }
    html.push('<div style="width: ',
        barWidth,
        'px; height: ',
        chartStyle.height,
        'px; background: url(',
        MyWater.IMGPATH, chartStyle.img,
        ') repeat top right;"></div>');
    if (headWidth > 0) {
      html.push('</td><td><img src="',
          MyWater.IMGPATH, chartStyle.headImg,
          '" width="', headWidth, '" height="',
          chartStyle.height, '" /></td></tr></table>');
    }
    document.getElementById(bar.domId).innerHTML = html.join('');
  }
  
  // Draw the current selection
  this.setSelection(this.selection);

  // Attach event handlers if clickable
  if (options.canSelect !== false) {
    for (var i = 0; i < bars.length; i++) {
      var bar = bars[i];
      var td = document.getElementById(bar.domId);
      td.style.cursor = 'pointer';
      td.onclick = this.createListener(bar.dataRow, bar.dataCol);
    }  
  }
};

MyWater.prototype.createListener = function(row, col) {
  var self = this;
  return function() { self.handleClick(row, col); }
};

MyWater.prototype.handleClick = function(row, col) {
  this.setSelection([{row:row, col:col}]);
  google.visualization.events.trigger(this, 'select', {});
};

MyWater.prototype.getSelection = function() {
  return this.selection;
};

MyWater.prototype.setSelection = function(coords) {
  if (!coords) {
    coords = [];
  }
  this.selection = coords;
  var bars = this.bars;
  for (var i = 0; i < bars.length; i++) {
    var bar = bars[i];
    var className = 'MyWater-bar';
    for (var c = 0; c < coords.length; c++) {
      var rowInd = coords[c].row;
      var colInd = coords[c].col;
    if ((rowInd != null && bar.dataRow == rowInd) || 
        (colInd != null && bar.dataCol == colInd)) {
      className += 'hi';
      break;
    }  
    }
    var td = document.getElementById(bar.domId);
    if (td.className != className) {
      td.className = className;
    }
  }
}
